package com.cuit.xsc.weishare.oauth;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import android.content.Context;

import com.cuit.xsc.weishare.util.Base64;
import com.cuit.xsc.weishare.util.Base64Encoder;
import com.cuit.xsc.weishare.util.HMAC_SHA1;
import com.cuit.xsc.weishare.util.LogUtil;
import com.cuit.xsc.weishare.util.OAuthConfigUtil;




public class OAuth {
	private static Random random = new Random();
	private String encoding = "utf-8"; //URL编码方式
	private String oauth_request_method = "GET"; // 请求方法
	private String Base_url; // 请求url
	private String oauth_consumer_key; // —— 注册应用后由应用服务商提供
	private String consumer_secret; // —— 注册应用后由应用服务商提供
	private static String oauth_token;
	private static String oauth_token_secret;
	private String oauth_verifier; //验证码
	private String oauth_callback = "www.weishare.com"; // —— 用户授权后的返回地址
	private String oauth_nonce; // —— 随机字符串，须保证每次都不同 （32个字符长度）
	private String oauth_timestamp; // —— 时间戳
	private static String oauth_signature_method = "HMAC-SHA1"; // —— 签名base string 的方法，目前支持
	// HMAC-SHA1
	private String oauth_version = "1.0"; // —— Oauth协议版本
	private String oauth_signature; // oauth请求签 名
	
	private static OAuth instance;

	public void setOauthTokenAndOauthTokenSercet(String oauth_token,String oauth_token_secret,String oauth_verifier){
		this.oauth_token = oauth_token;
		this.oauth_token_secret = oauth_token_secret;
		this.oauth_verifier = oauth_verifier;
	}
	
	/**
	 * 初始化oauth_token、oauth_token_secret、oauth_verifier
	 */
	public void clear(){
		this.oauth_token = null;
		this.oauth_token_secret = null;
		this.oauth_verifier = null;
	}
	
	
	
	public String getAuthorizUrl()
	{
		String result = null;
		WeiboParameters parameters = new WeiboParameters();
		parameters.add("oauth_callback", OAuthConfigUtil.callBackUrl);
		try
		{
			parameters = getHttParameters("GET", OAuthConfigUtil.getInstance().getRequest_token_url(), parameters, null, null);
			SyncHttp http = new SyncHttp();
			result = http.httpGet(OAuthConfigUtil.getInstance().getRequest_token_url(), parameters);
		}
		catch (Throwable e)
		{
			e.printStackTrace();
		}
		return result;
	}
	
	public static synchronized OAuth getInstance(){
		if(instance == null){
			instance = new OAuth();
		}
		return instance;
	} 
	
	private OAuth() {

	}
	
	public void setKeyAndSecret(String key,String secret){		
		this.oauth_consumer_key = key;
		this.consumer_secret = secret;	
	}
	
	/**
	 * 拼接请求的url
	 * 	
	 * @return Query String
	 * @throws Exception
	 */
	public String getRequestUrl() throws Exception{
		this.oauth_nonce = getAauth_nonce();
		this.oauth_timestamp = getAauth_timestamp();
		String baseUrlString = this.getBaseString();
		this.oauth_signature = this.getAauth_signature(baseUrlString);
//		return Base_url + "?"+baseUrlString + "&oauth_signature=" + URLEncoder.encode(oauth_signature,encoding);
		return baseUrlString + "&oauth_signature=" + URLEncoder.encode(oauth_signature,encoding);
	}
	
	/**
	 * 获取随机的 oauth_nonce
	 * 
	 * @return
	 */
	public static String getAauth_nonce() {
		return String.valueOf(random.nextInt(9876599) + 123400);
	}

	/**
	 * 获取时间戳
	 * 
	 * @return
	 */
	public static String getAauth_timestamp() {
		return String.valueOf(System.currentTimeMillis()).substring(0, 10);
	}

	/**
	 * 拼接所有参数
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public String getBaseString() throws UnsupportedEncodingException {
		
		String bsss = "";
		String curWeibo = OAuthConfigUtil.getInstance().getCurWeibo();
		
		if((oauth_verifier == null || oauth_verifier.length() == 0) && !curWeibo.equals(OAuthConfigUtil.WANGYIW)){
			bsss +="oauth_callback=" + URLEncoder.encode(OAuthConfigUtil.callBackUrl, encoding) + "&";
		}
		bsss += "oauth_consumer_key=" + URLEncoder.encode(oauth_consumer_key, encoding);
		bsss += "&oauth_nonce=" + URLEncoder.encode(oauth_nonce, encoding);
		bsss += "&oauth_signature_method=" + URLEncoder.encode(oauth_signature_method, encoding); 
		bsss += "&oauth_timestamp=" + URLEncoder.encode(oauth_timestamp, encoding);
		
		if(oauth_token != null && (oauth_token.length() > 0)){
			bsss += "&oauth_token=" + URLEncoder.encode(oauth_token, encoding); 
		}
		if(oauth_verifier != null && oauth_verifier.length() >0){
			bsss += "&oauth_verifier=" + URLEncoder.encode(oauth_verifier, encoding); 
		}		
				
		bsss += "&oauth_version=" + URLEncoder.encode(oauth_version, encoding);
		
		return bsss;
	}
	
	


	/**
	 * 获取 oauth_signature
	 * @param data
	 * @param key
	 * @return
	 */
	public String getAauth_signature(String data) throws Exception{
		byte[] byteHMAC = null;
//		oauth_request_method = "GET";
//		Base_url = "http://180.149.135.224/oauth/request_token";
//		encoding = "utf-8";
//		consumer_secret="417466d2685f80420e60e8cec068fcec";
		try {
			String bss = oauth_request_method + "&" + URLEncoder.encode(Base_url, encoding) + "&";
			String bsss = URLEncoder.encode(data, encoding);
			//LogUtil.i(OAuth.class, "r_baseString= "+data);
			String urlString = bss +bsss;
			//LogUtil.i(OAuth.this, "r_urlString"+urlString);
			LogUtil.i(OAuth.class, "o_signatureBase="+urlString);
			String oauthKey =  URLEncoder.encode(consumer_secret, encoding) + "&"
			+ ((oauth_token_secret == null || oauth_token_secret.equals("")) ? "" : URLEncoder.encode(oauth_token_secret,encoding));
			LogUtil.i(OAuth.class, "o_oauthKey="+oauthKey);
			Mac mac = Mac.getInstance("HmacSHA1");
			SecretKeySpec spec = new SecretKeySpec(oauthKey.getBytes("US-ASCII"), "HmacSHA1");
			mac.init(spec);
			byteHMAC = mac.doFinal((urlString).getBytes("US-ASCII"));
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException ignore) {
			
		}
		
		String oauthSignature = new Base64Encoder().encode(byteHMAC);
		LogUtil.i(OAuth.class, "signature="+oauthSignature);
		return oauthSignature;
	}
	
	public String getAauth_signature(String data, WeiboParameters parameters) throws Exception{
		byte[] byteHMAC = null;
		try {
			String bss = oauth_request_method + "&" + URLEncoder.encode(Base_url, encoding) + "&";
			String bsss = URLEncoder.encode(data, encoding);
			//LogUtil.i(OAuth.class, "r_baseString="+bsss);
			String urlString = bss +bsss;
			
			String oauthKey =  URLEncoder.encode(consumer_secret, encoding) + "&"
			+ ((oauth_token_secret == null || oauth_token_secret.equals("")) ? "" : URLEncoder.encode(oauth_token_secret,encoding));
			LogUtil.i(OAuth.class, "o_oauthKey="+oauthKey);
			Mac mac = Mac.getInstance("HmacSHA1");
			SecretKeySpec spec = new SecretKeySpec(oauthKey.getBytes("US-ASCII"), "HmacSHA1");
			mac.init(spec);
			byteHMAC = mac.doFinal((urlString).getBytes("US-ASCII"));
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException ignore) {
			
		}
		
		String oauthSignature = new Base64Encoder().encode(byteHMAC);
		return oauthSignature;
	}
	
	/**
	 * 获取 oauth_token
	 * @return
	 */
	public String getOauthToken(Context context){
		String oauthToken = null;
		this.Base_url = OAuthConfigUtil.getInstance().getRequest_token_url();
		
		try {
			
			String url = this.getRequestUrl();
			LogUtil.d(OAuth.this, "获取未经授权的token requst_token_url = "+url);
			
			//oauthToken = HttpClientUtil.get(url,"utf-8");
			
			SyncHttp http = new SyncHttp();
			oauthToken = http.httpGet(Base_url, url);
			
			if (oauthToken == null)
			{
				LogUtil.e(this, "获取AccessToken失败");
			}
			
			LogUtil.d(OAuth.this,"未经授权的oauthToken = "+oauthToken);
		} catch (Exception e) {
            e.printStackTrace();
        }
        
        return oauthToken;
	}
	
	/**
	 * 获取AccessToken
	 * 
	 * @return
	 */
	public String getAccessToken(){
		String oauthToken = null;
		this.Base_url = OAuthConfigUtil.getInstance().getAccess_token_url();
		
		try {
			String url = this.getRequestUrl();
			LogUtil.d(OAuth.this,"取得授权成功的请求 = "+getRequestUrl());
			
			oauthToken = HttpClientUtil.get(url,"utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("getAccessToken() Exception");	
        }
        
        return oauthToken;
	}

	public void setOauth_callback(String oauthCallback) {
		oauth_callback = oauthCallback;
	}
	
	/**
	 * 获取授权URL
	 * 		用户登录页面地址
	 * @return 授权URL
	 */
	public String getAuthorizUrl(Context context){
		
		String oauthToken =this. getOauthToken(context);
	    
	    try {
	    	String[] oauth = oauthToken.split("&");
			String[] oauthTokenTmp = oauth[0].split("=");
			oauth_token = oauthTokenTmp[1];
			String tmp = oauth[1];
			String[] tmps = tmp.split("=");
			oauth_token_secret = tmps[1];
        } catch (Exception e) {
        	e.printStackTrace();
        }
        
        String token = "oauth_token="+oauth_token;
        LogUtil.d(this, "oauth token = "+token);
		String url = OAuthConfigUtil.getInstance().getAuthoriz_token_url()+"?"+token;
		String curWeibo = OAuthConfigUtil.getInstance().getCurWeibo();
		try
		{
			if (curWeibo.equals(OAuthConfigUtil.WANGYIW) || curWeibo.equals(OAuthConfigUtil.SOHUW))
			{
				url = OAuthConfigUtil.getInstance().getAuthoriz_token_url() + "?"
						+ token + "&" + "oauth_callback="
						+ URLEncoder.encode(OAuthConfigUtil.callBackUrl, "utf-8")
						+ "&client_type=mobile";
			}
		} catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
		
		LogUtil.d(OAuth.this, "请求授权页面的url[] = "+url);
		return url;
	}
	
	/**
	 *  设置验证码
	 * @param oauthVerifier 验证码
	 */
	public void setOauthVerifier(String oauthVerifier) {
	    this.oauth_verifier = oauthVerifier;
    }
	

	public String getOauth_token() {
    	return oauth_token;
    }

	public void setOauth_token(String oauthToken) {
    	oauth_token = oauthToken;
    }

	public String getOauth_token_secret() {
    	return oauth_token_secret;
    }

	public void setOauth_token_secret(String oauthTokenSecret) {
    	oauth_token_secret = oauthTokenSecret;
    }
	
	/**
	 * 生成请求的参数
	 * @param httpMethod
	 * @param url
	 * @param parameters
	 * @param token
	 * @param tokenSecret
	 * @return
	 * @throws Throwable
	 */
	public static WeiboParameters getHttParameters(String httpMethod, String url, WeiboParameters parameters, String token, String tokenSecret) throws Throwable
	{
		parameters = addBaseParameters(parameters);
		if (token != null)
		{
			parameters.add("oauth_token", token);
		}
		
		String signature = generateSignature(httpMethod, url, parameters, OAuthConfigUtil.getInstance().getAppSecret(), tokenSecret);
		parameters.add("oauth_signature", encode(signature));
		return parameters;
	}
	
	
	public static WeiboParameters addBaseParameters(WeiboParameters parameters)
	{
		
		if (parameters == null)
		{
			parameters = new WeiboParameters();
		}
		else 
		{
			String key = null;
			String value = null;
			for (int i = 0; i < parameters.size(); i++)
			{
				key = parameters.getKey(i);
				value = parameters.getValue(key);
				parameters.add(key, encode(value));
			}
			
		}
		String key = "oauth_consumer_key";
		parameters.add(key, encode(OAuthConfigUtil.getInstance().getAppKey()));	
		key = "oauth_nonce";
		parameters.add(key,encode(getAauth_nonce()) );
		key = "oauth_signature_method";
		parameters.add(key, encode(oauth_signature_method));
		key = "oauth_timestamp";
		parameters.add(key, encode(getAauth_timestamp()));
		key = "oauth_version";
		parameters.add(key, encode("1.0"));		
		return parameters;
		
	}
	
	
	/**
	 * 产生签名值
	 * 
	 * @param method
	 *            请求方法
	 * @param url
	 *            请求路径
	 * @param params
	 *            请求参数集合
	 * @param consumerSecret
	 *            AppSecret
	 * @param tokenSecret
	 *            tokenSecret
	 * @return
	 * @throws Exception
	 */
	public static String generateSignature(String method, String url, WeiboParameters params, String consumerSecret, String tokenSecret) throws Exception
	{
		// 获取源串
		String signatureBase = getBaseString(method, url, params);
		// 构造密钥
		String oauthKey = "";
		if (null == tokenSecret || tokenSecret.equals(""))
		{
			oauthKey = encode(consumerSecret) + "&";
		} else
		{
			oauthKey = encode(consumerSecret) + "&" + encode(tokenSecret);
		}
		LogUtil.i(OAuth.class, "n_signatureBase="+signatureBase);
		LogUtil.i(OAuth.class, "n_oauthKey="+oauthKey);
		
		// 生成签名值
		byte[] encryptBytes = HMAC_SHA1.HmacSHA1Encrypt(signatureBase, oauthKey);
		return Base64.encode(encryptBytes);
		
		
//		Mac mac = Mac.getInstance("HmacSHA1");
//		SecretKeySpec spec = new SecretKeySpec(oauthKey.getBytes("US-ASCII"), "HmacSHA1");
//		mac.init(spec);
//		byte[] byteHMAC = mac.doFinal((signatureBase).getBytes("US-ASCII"));
//		return new Base64Encoder().encode(byteHMAC);
		
	}
	
	public static String generateSignature(String signatureBase, String oauthKey) throws Exception
	{
//		byte[] encryptBytes = HMAC_SHA1.HmacSHA1Encrypt(signatureBase, oauthKey);
//		return Base64.encode(encryptBytes);
		
		
		Mac mac = Mac.getInstance("HmacSHA1");
		SecretKeySpec spec = new SecretKeySpec(oauthKey.getBytes("US-ASCII"), "HmacSHA1");
		mac.init(spec);
		byte[] byteHMAC = mac.doFinal((signatureBase).getBytes("US-ASCII"));
		return new Base64Encoder().encode(byteHMAC);
	}
	
	
 public static String getBaseString(String httpMethod, String url, WeiboParameters signatureParams) throws UnsupportedEncodingException 
 {
		
	StringBuffer base = new StringBuffer(httpMethod.toUpperCase()).append("&").append(encode(url.toLowerCase())).append("&");
	base.append(encode(encodeParameters(signatureParams, "&", false)));	
	LogUtil.i(OAuth.class, "w_baseString="+base);
	return base.toString();	
	
	
}
	
	/**
	 * 构造参数请求
	 * @param postParams 参数
	 * @param splitter 连接符
	 * @param quot 是否需要加引号
	 * @return
	 */
	public static String encodeParameters(WeiboParameters postParams, String splitter, boolean quot) 
	{
		StringBuffer buf = new StringBuffer();
		postParams.sort();   //将参数排序
		for (int i = 0; i < postParams.size(); i++)
		{
			if (buf.length() != 0)
			{
				if (quot)
				{
					buf.append("\"");
				}
				buf.append(splitter);
			}
			buf.append(postParams.getKey(i)).append("=");
			if (quot)
			{
				buf.append("\"");
			}
			buf.append(postParams.getValue(i));
		}
		if (buf.length() != 0)
		{
			if (quot)
			{
				buf.append("\"");
			}
		}
		return buf.toString();
	}
	
	/**
     * @param value string to be encoded
     * @return encoded parameters string
     */
    public static String encode(String value) {
        String encoded = null;
        try {
            encoded = URLEncoder.encode(value, "UTF-8");
        } catch (UnsupportedEncodingException ignore) {
        }
        StringBuffer buf = new StringBuffer(encoded.length());
        char focus;
        for (int i = 0; i < encoded.length(); i++) {
            focus = encoded.charAt(i);
            if (focus == '*') {
                buf.append("%2A");
            } else if (focus == '+') {
                buf.append("%20");
            } else if (focus == '%' && (i + 1) < encoded.length()
                    && encoded.charAt(i + 1) == '7' && encoded.charAt(i + 2) == 'E') {
                buf.append('~');
                i += 2;
            } else {
                buf.append(focus);
            }
        }
        return buf.toString();
    }
	
}
